CloudFormationスタックをリファクタリングしてみた
CloudFormationにインポート機能が追加されたことで作成済みスタックのリファクタリングができるようになりました。今回は実際にリファクタリングしてみたいと思います。
目次
概要
上記のように1つのスタックですべてのリソースを管理しているとします。これを下記のように2つのスタックに分割したいと思います。分割の方針としてはネットワークレイヤとアプリケーションレイヤというイメージです。
準備
1つのテンプレートでリソースを作成
すべてのリソースが1つのテンプレートで作成されている状態にします。下記のテンプレートをdemo.ymlとして保存します。今回はマネジメントコンソールを利用し、スタック名をdemo-stack
とします。これで準備は完了です。
AWSTemplateFormatVersion: '2010-09-09' Resources: # VPC DemoVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 Tags: - Key: Name Value: demo-vpc # サブネット DemoPriSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: 'ap-northeast-1a' CidrBlock: 10.0.1.0/24 VpcId: !Ref DemoVpc Tags: - Key: Name Value: demo-pri-subnet # セキュリティグループ DemoSG: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: DemoSG GroupName: demo-sg VpcId: !Ref DemoVpc Tags: - Key: 'Name' Value: 'demo-sg' SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 #インスタンス DemoWeb: Type: 'AWS::EC2::Instance' Properties: ImageId: 'ami-079e6fb1e856e80c1' InstanceType: 't2.micro' SecurityGroupIds: - !GetAtt DemoSG.GroupId SubnetId: !Ref DemoPriSubnet Tags: - Key: 'Name' Value: 'demo-web'
リファクタリング
リソースが削除されないようにする
これからリファクタリングを行っていきますが、このまま管理外にするとセキュリティグループとEC2が削除されてしまいます。管理外にする前にDeletionPolicy
属性をRetain
に更新します。これによりテンプレートからリソースの記述を削除した場合でもリソースが保持されます。下記が更新したdemo.ymlです。
AWSTemplateFormatVersion: '2010-09-09' Resources: # VPC DemoVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 Tags: - Key: Name Value: demo-vpc # サブネット DemoPriSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: 'ap-northeast-1a' CidrBlock: 10.0.1.0/24 VpcId: !Ref DemoVpc Tags: - Key: Name Value: demo-pri-subnet # セキュリティグループ DemoSG: Type: "AWS::EC2::SecurityGroup" DeletionPolicy: Retain # ← 追加行 Properties: GroupDescription: DemoSG GroupName: demo-sg VpcId: !Ref DemoVpc Tags: - Key: 'Name' Value: 'demo-sg' SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 #インスタンス DemoWeb: Type: 'AWS::EC2::Instance' DeletionPolicy: Retain # ← 追加行 Properties: ImageId: 'ami-079e6fb1e856e80c1' InstanceType: 't2.micro' SecurityGroupIds: - !GetAtt DemoSG.GroupId SubnetId: !Ref DemoPriSubnet Tags: - Key: 'Name' Value: 'demo-web1'
マネジメントコンソールからdemo-stack
を選択 → 「更新する」→「既存のテンプレートを置き換える」→「テンプレートファイルのアップロード」より上記の更新したテンプレートをアップロードします。
「変更はありません」と表示されていますが、そのままスタックを更新します。
イベントを確認するとEC2とセキュリティグループが更新されていることがわかります。
スタックから分割するリソースを管理外にする
リソースを管理外にするにはテンプレートからリソースを削除してスタックを更新します。下記はEC2とセキュリティグループの記述を削除したものです。加えて、分割するテンプレートからVPCとサブネットをクロススタック参照できるように、VPCとSubnetのIDを出力しています。
AWSTemplateFormatVersion: '2010-09-09' Resources: # VPC DemoVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 Tags: - Key: Name Value: demo-vpc # サブネット DemoPriSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: 'ap-northeast-1a' CidrBlock: 10.0.1.0/24 VpcId: !Ref DemoVpc Tags: - Key: Name Value: demo-pri-subnet Outputs: DemoVpc: Value: !Ref DemoVpc Export: Name: DemoVpc DemoPriSubnet: Value: !Ref DemoPriSubnet Export: Name: DemoPriSubnet
demo-nw.yml
として保存し、先程と同じようにテンプレートをアップロードしてスタックを更新します。
変更セットにはEC2インスタンスとセキュリティグループが削除されると表示されていますが、このまま更新します。
イベントを確認するとEC2インスタンスとセキュリティグループはDELETE_SKIPPED
となっており実際には削除されていないことが確認できます。EC2画面でも確認してみてください。
管理外にしたリソースをあたらしいスタックにインポート
新しいスタック用に下記のテンプレートをdemo-app.yml
として保存します。VpcId
、SubnetId
をImportValue
にしています。また、インポートするリソースはDeletionPolicy
をRetain
にする必要があります。
AWSTemplateFormatVersion: '2010-09-09' Resources: # セキュリティグループ DemoSG: Type: "AWS::EC2::SecurityGroup" DeletionPolicy: Retain Properties: GroupDescription: DemoSG GroupName: demo-sg VpcId: !ImportValue DemoVpc Tags: - Key: 'Name' Value: 'demo-sg' SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 #インスタンス DemoWeb: Type: 'AWS::EC2::Instance' DeletionPolicy: Retain Properties: ImageId: 'ami-079e6fb1e856e80c1' InstanceType: 't2.micro' SecurityGroupIds: - !GetAtt DemoSG.GroupId SubnetId: !ImportValue DemoPriSubnet Tags: - Key: 'Name' Value: 'demo-web'
次に「既存のリソースを仕様(リソースをインポート)」を選択します。
「概要をインポート」では「次へ」をクリック
上記テンプレートをアップロードし「次へ」をクリック
インポートするEC2インスタンスのInstanceId
とセキュリティグループのGroupId
を入力し「次へ」をクリック
スタック名にdemo-app-stack
と入力し「次へ」をクリック
変更にEC2インスタンスとセキュリティグループがImport
と表示されていることを確認し「リソースをインポート」をクリック
IMPORT_COMPLETE
と表示されたらリソースを確認します。EC2インスタンスとセキュリティグループが管理下にあることが確認できます。
最初に作成したスタックにはVPCとサブネットのみが管理下に置かれています。
これでリファクタリングは完了です。
まとめ
スタックがリファクタリングできることを確認しました。巨大なスタックを管理している場合は分割することでメンテナンスしやすくなることもあります。運用にお困りの方はリファクタリングを検討してみてはいかがでしょうか。
ただ、運用環境で行う場合は、事前に検証を行ってください。